#include "complexVec.h"
#include "complexMat.h"
#include <cassert>

namespace moremath{

	Vecd Vecc::re(){
		Vecd realVec(mNumElts, vl_0);
		for(int i=0; i<mNumElts; i++) realVec[i] = mVec[i].re();
		return realVec;
	}

	Vecd Vecc::im(){
		Vecd imagVec(mNumElts, vl_0);
		for(int i=0; i<mNumElts; i++) imagVec[i] = mVec[i].im();
		return imagVec;

	}
	void Vecc::setReal(Vecd &_real){
		assert(_real.Elts()==mNumElts);
		for(int i=0; i<mNumElts; i++) mVec[i].re() = _real[i];
	}
	void Vecc::setImag(Vecd &_imag){
		assert(_imag.Elts()==mNumElts);
		for(int i=0; i<mNumElts; i++) mVec[i].im() = _imag[i];
	}
	void Vecc::operator = (Vecc _v){
		mNumElts = _v.Elts();
		mVec.resize(mNumElts);
		for(int i=0; i<mNumElts; i++) mVec[i]= _v[i];
	}
	Vecc Vecc::operator + (Vecc& _v){
		assert(_v.Elts()==mNumElts);
		Vecc vnew(mNumElts);
		for(int i=0; i<mNumElts; i++) vnew[i]=mVec[i]+_v[i];
		return vnew;
	}
	void Vecc::operator += (Vecc& _v){
		assert(_v.Elts()==mNumElts);
		for(int i=0; i<mNumElts; i++) mVec[i]+=_v[i];
	}
	Vecc Vecc::operator - (){
		Vecc vneg(mNumElts);
		for(int i=0; i<mNumElts; i++) vneg[i]= -mVec[i];
		return vneg;
	}
	Vecc Vecc::operator - (Vecc &_v){
		assert(_v.Elts()==mNumElts);
		Vecc vneg(mNumElts);
		for(int i=0; i<mNumElts; i++) vneg[i]= mVec[i]-_v[i];
		return vneg;
	}
	Vecc Vecc::operator * (double _s){
		Vecc v(mNumElts);
		for(int i=0; i<mNumElts; i++) v[i]= mVec[i]*_s;
		return v;
	}
	Vecc Vecc::operator *(complex _q){
		Vecc v(mNumElts);
		for(int i=0; i<mNumElts; i++) v[i]= mVec[i]*_q;
		return v;
	}
	Vecc Vecc::operator *(Vecc &_v2){
		Vecc v(mNumElts);
		for(int i=0; i<mNumElts; i++) v[i]= mVec[i]*_v2[i];
		return v;
	}
	Vecc Vecc::operator *(Vecd &_v2){
		Vecc v(mNumElts);
		for(int i=0; i<mNumElts; i++) v[i]= mVec[i]*_v2[i];
		return v;
	}
	void Vecc::operator *= (double _s){
		for(int i=0; i<mNumElts; i++) mVec[i]*=_s;
	}
	void Vecc::operator *=(Vecc &_v2){
		for(int i=0; i<mNumElts; i++) mVec[i]*=_v2[i];
	}

	Vecc Vecc::operator / (double _s){
		Vecc v(mNumElts);
		for(int i=0; i<mNumElts; i++) v[i]= mVec[i]/_s;
		return v;
	}
	Vecc Vecc::operator / (complex _c){
		Vecc v(mNumElts);
		for(int i=0; i<mNumElts; i++) v[i]= mVec[i]/_c;
		return v;
	}
	Vecc Vecc::operator / (Vecc &_v){
		assert(_v.Elts()==mNumElts);
		Vecc vnew(mNumElts);
		for(int i=0; i<mNumElts; i++) vnew[i]= mVec[i]/_v[i];
		return vnew;
	}

	Vecc Vecc::conj(){
		Vecc v(mNumElts);
		for(int i=0; i<mNumElts; i++) v[i]= mVec[i].conj();
		return v;
	}
	double Vecc::norm(){
	  Vecc conjugate = conj();
	  Vecc vvc = (*this) * conjugate;
		double normv=0;
		for(int i=0; i<mNumElts; i++) {
			normv += vvc[i].re();
		}
		return sqrt(normv);
	}

	Matc Vecc::operator * (Matc &_m){
		assert(mNumElts==_m.Rows());
		Matc mnew(_m.Rows(), _m.Cols());
		for(int i=0; i<mNumElts; i++){
			mnew[i] = _m[i]*mVec[i];
		}
		return mnew;
	}

}

ostream& operator <<(ostream &out, moremath::Vecc &_v){
	out<<"[";
	for(int i=0; i<_v.Elts(); i++) out<<_v[i]<<" ";
	out<<"]";
	return out;
}

moremath::Vecc exp(moremath::Vecc v){
	for(int i=0; i<v.Elts(); i++){
		v[i] = exp(v[i]);
	}
	return v;
}

moremath::Vecc sqrt(moremath::Vecc _v){
	for(int i=0; i<_v.Elts(); i++){
		_v[i] = sqrt(_v[i]);
	}
	return _v;
}

moremath::complex cdot(moremath::Vecc v1, moremath::Vecc v2){
	assert(v1.Elts()==v2.Elts());
	moremath::complex dotp(0,0);
	for(int i=0; i<v1.Elts(); i++) dotp += v1[i]*v2[i];
	return dotp;
}

moremath::complex cdot(moremath::Vecc v1, Vecd v2){
	assert(v1.Elts()==v2.Elts());
	moremath::complex dotp(0,0);
	for(int i=0; i<v1.Elts(); i++) dotp += v1[i]*v2[i];
	return dotp;
}

moremath::complex cdot(Vecd v2, moremath::Vecc v1){return cdot(v1,v2);}
